/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;

namespace FaceCat {
    /// <summary>
    /// 单元格事件
    /// </summary>
    /// <param name="sender">发送者</param>
    /// <param name="cell">单元格</param>
    public interface FCGridCellEventCallBack {
        /// <summary>
        /// 单元格事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="cell"></param>
        /// <param name="invoke"></param>
        void callGridCellEvent(String eventName, Object sender, FCGridCell cell, Object invoke);
    }

    /// <summary>
    /// 单元格触摸事件委托
    /// </summary>
    /// <param name="sender">发送者</param>
    /// <param name="cell">单元格</param>
    /// <param name="touchInfo">触摸信息</param>
    public interface FCGridCellTouchEventCallBack {
        /// <summary>
        /// 单元格触摸事件委托
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="cell"></param>
        /// <param name="touchInfo"></param>
        /// <param name="invoke"></param>
        void callGridCellTouchEvent(String eventName, Object sender, FCGridCell cell, FCTouchInfo touchInfo, Object invoke);
    }

    /// <summary>
    /// 表格排序类
    /// </summary>
    public class FCGridSort {
        /// <summary>
        /// 表格排序类
        /// </summary>
        public class FCGridRowCompare : IComparer<FCGridRow> {
            /// <summary>
            /// 列索引
            /// </summary>
            public int m_columnIndex;

            /// <summary>
            /// 类型
            /// </summary>
            public int m_type;

            /// <summary>
            /// 比较方法
            /// </summary>
            /// <param name="x">行X</param>
            /// <param name="y">行Y</param>
            /// <returns>结果</returns>
            public int Compare(FCGridRow x, FCGridRow y) {
                FCGridCell cellLeft = x.getCell(m_columnIndex);
                FCGridCell cellRight = y.getCell(m_columnIndex);
                if (cellLeft != null && cellRight != null)
                {
                    if (m_type == 0)
                    {
                        return cellRight.compareTo(cellLeft);
                    }
                    else
                    {
                        return cellLeft.compareTo(cellRight);
                    }
                }
                else
                {
                    return 1;
                }
            }
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="grid">表格</param>
        /// <param name="column">列</param>
        /// <param name="sortMode">排序方式</param>
        public virtual void sortColumn(FCGrid grid, FCGridColumn column, FCGridColumnSortMode sortMode) {
            FCGridRowCompare compare = new FCGridRowCompare();
            compare.m_columnIndex = column.getIndex();
            if (sortMode == FCGridColumnSortMode.Asc) {
                compare.m_type = 1;
            }
            try
            {
                grid.m_rows.Sort(compare);
            }
            catch (Exception ex)
            {
            }
        }
    }

    /// <summary>
    /// 表格视图
    /// </summary>
    public class FCGrid : FCDiv {
        /// <summary>
        /// 创建表格
        /// </summary>
        public FCGrid() {
            setShowHScrollBar(true);
            setShowVScrollBar(true);
        }

        /// <summary>
        /// 动画添加的行
        /// </summary>
        public ArrayList<FCGridRow> m_animateAddRows = new ArrayList<FCGridRow>();

        /// <summary>
        /// 动画移除的行
        /// </summary>
        public ArrayList<FCGridRow> m_animateRemoveRows = new ArrayList<FCGridRow>();

        /// <summary>
        /// 列的集合
        /// </summary>
        public ArrayList<FCGridColumn> m_columns = new ArrayList<FCGridColumn>();

        /// <summary>
        /// 正在编辑的单元格
        /// </summary>
        public FCGridCell m_editingCell;

        /// <summary>
        /// 正在编辑的行
        /// </summary>
        public FCGridRow m_editingRow;

        /// <summary>
        /// 是否包含不可见行
        /// </summary>
        public bool m_hasUnVisibleRow = false;

        /// <summary>
        /// 是否锁定界面更新
        /// </summary>
        public bool m_lockUpdate = false;

        /// <summary>
        /// 行的集合
        /// </summary>
        public ArrayList<FCGridRow> m_rows = new ArrayList<FCGridRow>();

        /// <summary>
        /// 秒表ID
        /// </summary>
        private int m_timerID = getNewTimerID();

        /// <summary>
        /// 触摸按下时的位置
        /// </summary>
        public FCPoint m_touchDownPoint;

        public bool m_allowDragRow;

        /// <summary>
        /// 获取是否允许拖动行
        /// </summary>
        public virtual bool allowDragRow() {
            return m_allowDragRow;
        }

        /// <summary>
        /// 设置是否允许拖动行
        /// </summary>
        public virtual void setAllowDragRow(bool value) {
            m_allowDragRow = value;
        }

        /// <summary>
        /// 获取所有可见列的宽度
        /// </summary>
        /// <returns></returns>
        public virtual int getAllVisibleColumnsWidth() {
            int allVisibleColumnsWidth = 0;
            int columnSize = m_columns.size();
            for (int i = 0; i < columnSize; i++) {
                FCGridColumn column = m_columns.get(i);
                if (column.isVisible()) {
                    allVisibleColumnsWidth += column.getWidth();
                }
            }
            return allVisibleColumnsWidth;
        }

        public bool m_allowHoveredRow = true;

        /// <summary>
        /// 获取是否允许悬停行
        /// </summary>
        public virtual bool allowHoveredRow() {
            return m_allowHoveredRow;
        }

        /// <summary>
        /// 设置是否允许悬停行
        /// </summary>
        public virtual void setAllowHoveredRow(bool value) {
            m_allowHoveredRow = value;
        }

        /// <summary>
        /// 获取所有可见行的高度
        /// </summary>
        public virtual int getAllVisibleRowsHeight() {
            int allVisibleRowsHeight = 0;
            int rowSize = m_rows.size();
            for (int i = 0; i < rowSize; i++) {
                if (m_rows.get(i).isVisible()) {
                    allVisibleRowsHeight += m_rows.get(i).getHeight();
                }
            }
            return allVisibleRowsHeight;
        }

        public FCGridRowStyle m_alternateRowStyle;

        /// <summary>
        /// 获取交替行的样式
        /// </summary>
        public virtual FCGridRowStyle getAlternateRowStyle() {
            return m_alternateRowStyle;
        }

        /// <summary>
        /// 设置交替行的样式
        /// </summary>
        public virtual void setAlternateRowStyle(FCGridRowStyle value) {
            m_alternateRowStyle = value;
        }

        public FCGridCellEditMode m_cellEditMode = FCGridCellEditMode.SingleClick;

        /// <summary>
        /// 获取单元格编辑模式
        /// </summary>
        public virtual FCGridCellEditMode getCellEditMode() {
            return m_cellEditMode;
        }

        /// <summary>
        /// 设置单元格编辑模式
        /// </summary>
        public virtual void setCellEditMode(FCGridCellEditMode value) {
            m_cellEditMode = value;
        }

        public FCTextBox m_editTextBox;

        /// <summary>
        /// 获取编辑文本框
        /// </summary>
        public virtual FCTextBox getEditTextBox() {
            return m_editTextBox;
        }

        public long m_gridLineColor = FCColor.rgb(100, 100, 100);

        /// <summary>
        /// 获取网格线的颜色
        /// </summary>
        public virtual long getGridLineColor() {
            return m_gridLineColor;
        }

        /// <summary>
        /// 设置网格线的颜色
        /// </summary>
        public virtual void setGridLineColor(long value) {
            m_gridLineColor = value;
        }

        public bool m_headerVisible = true;

        /// <summary>
        /// 获取标题头是否可见
        /// </summary>
        public virtual bool isHeaderVisible() {
            return m_headerVisible;
        }

        /// <summary>
        /// 设置标题头是否可见
        /// </summary>
        public virtual void setHeaderVisible(bool value) {
            m_headerVisible = value;
        }

        public int m_headerHeight = 20;

        /// <summary>
        /// 获取标题头的高度
        /// </summary>
        public virtual int getHeaderHeight() {
            return m_headerHeight;
        }

        /// <summary>
        /// 设置标题头的高度
        /// </summary>
        public virtual void setHeaderHeight(int value) {
            m_headerHeight = value;
        }

        public int m_horizontalOffset = 0;

        /// <summary>
        /// 获取横向滚动距离
        /// </summary>
        public virtual int getHorizontalOffset() {
            return m_horizontalOffset;
        }

        /// <summary>
        /// 设置横向滚动距离
        /// </summary>
        public virtual void setHorizontalOffset(int value) {
            m_horizontalOffset = value;
        }

        public FCGridCell m_hoveredCell;

        /// <summary>
        /// 获取触摸悬停的单元格
        /// </summary>
        public virtual FCGridCell getHoveredCell() {
            return m_hoveredCell;
        }

        public FCGridRow m_hoveredRow;

        /// <summary>
        /// 获取触摸悬停的行
        /// </summary>
        public virtual FCGridRow getHoveredRow() {
            return m_hoveredRow;
        }

        public bool m_multiSelect = false;

        /// <summary>
        /// 获取是否多选
        /// </summary>
        public virtual bool multiSelect() {
            return m_multiSelect;
        }

        /// <summary>
        /// 设置是否多选
        /// </summary>
        public virtual void setMultiSelect(bool value) {
            m_multiSelect = value;
        }

        public FCGridRowStyle m_rowStyle = new FCGridRowStyle();

        /// <summary>
        /// 获取行的样式
        /// </summary>
        public virtual FCGridRowStyle getRowStyle() {
            return m_rowStyle;
        }

        /// <summary>
        /// 设置行的样式
        /// </summary>
        public virtual void setRowStyle(FCGridRowStyle value) {
            m_rowStyle = value;
        }

        public ArrayList<FCGridCell> m_selectedCells = new ArrayList<FCGridCell>();

        /// <summary>
        /// 获取选中的单元格
        /// </summary>
        public virtual ArrayList<FCGridCell> getSelectedCells() {
            return m_selectedCells;
        }

        /// <summary>
        /// 设置选中的单元格
        /// </summary>
        public virtual void setSelectedCells(ArrayList<FCGridCell> value) {
            m_selectedCells.clear();
            int selectedCellsSize = value.size();
            for (int i = 0; i < selectedCellsSize; i++) {
                m_selectedCells.add(value.get(i));
            }
            onSelectedCellsChanged();
        }

        public ArrayList<FCGridColumn> m_selectedColumns = new ArrayList<FCGridColumn>();

        /// <summary>
        /// 获取选中的列
        /// </summary>
        public virtual ArrayList<FCGridColumn> getSelectedColumns() {
            return m_selectedColumns;
        }

        /// <summary>
        /// 设置选中的列
        /// </summary>
        public virtual void setSelectedColumns(ArrayList<FCGridColumn> value) {
            m_selectedColumns.clear();
            int selectedColumnsSize = value.size();
            for (int i = 0; i < selectedColumnsSize; i++) {
                m_selectedColumns.add(value.get(i));
            }
            onSelectedColumnsChanged();
        }

        public ArrayList<FCGridRow> m_selectedRows = new ArrayList<FCGridRow>();

        /// <summary>
        /// 获取选中行
        /// </summary>
        public virtual ArrayList<FCGridRow> getSelectedRows() {
            return m_selectedRows;
        }

        /// <summary>
        /// 设置选中行
        /// </summary>
        public virtual void setSelectedRows(ArrayList<FCGridRow> value) {
            m_selectedRows.clear();
            m_selectedCells.clear();
            int selectedRowsSize = value.size();
            for (int i = 0; i < selectedRowsSize; i++) {
                m_selectedRows.add(value.get(i));
            }
            onSelectedRowsChanged();
        }

        public FCGridSelectionMode m_selectionMode = FCGridSelectionMode.SelectFullRow;

        /// <summary>
        /// 获取选中模式
        /// </summary>
        public virtual FCGridSelectionMode getSelectionMode() {
            return m_selectionMode;
        }

        /// <summary>
        /// 设置选中模式
        /// </summary>
        public virtual void setSelectionMode(FCGridSelectionMode value) {
            m_selectionMode = value;
        }

        public FCGridSort m_sort = new FCGridSort();

        /// <summary>
        /// 获取排序处理类
        /// </summary>
        public virtual FCGridSort getSort() {
            return m_sort;
        }

        /// <summary>
        /// 设置排序处理类
        /// </summary>
        public virtual void setSort(FCGridSort sort) {
            m_sort = sort;
        }

        public bool m_useAnimation = false;

        /// <summary>
        /// 获取是否使用动画
        /// </summary>
        public virtual bool useAnimation() {
            return m_useAnimation;
        }

        /// <summary>
        /// 设置是否使用动画
        /// </summary>
        public virtual void setUseAnimation(bool value) {
            m_useAnimation = value;
            if (m_useAnimation) {
                startTimer(m_timerID, 20);
            } else {
                stopTimer(m_timerID);
            }
        }

        public int m_verticalOffset = 0;

        /// <summary>
        /// 获取纵向滚动距离
        /// </summary>
        public virtual int getVerticalOffset() {
            return m_verticalOffset;
        }

        /// <summary>
        /// 设置纵向滚动距离
        /// </summary>
        public virtual void setVerticalOffset(int value) {
            m_verticalOffset = value;
        }

        /// <summary>
        /// 添加列
        /// </summary>
        /// <param name="column">列</param>
        public virtual void addColumn(FCGridColumn column) {
            column.setGrid(this);
            m_columns.add(column);
            int columnsSize = m_columns.size();
            for (int i = 0; i < columnsSize; i++) {
                m_columns.get(i).setIndex(i);
            }
            addView(column);
            m_mustUpdate = true;
        }

        /// <summary>
        /// 添加行
        /// </summary>
        /// <param name="row">行</param>
        public virtual void addRow(FCGridRow row) {
            if (m_mustUpdate) {
                update();
                m_mustUpdate = false;
            }
            row.setGrid(this);
            m_rows.add(row);
            row.onAdd();
            if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                int selectedRowsSize = m_selectedRows.size();
                if (selectedRowsSize == 0) {
                    m_selectedRows.add(row);
                    onSelectedRowsChanged();
                }
            }
        }

        /// <summary>
        /// 动画添加行
        /// </summary>
        /// <param name="row">行</param>
        public virtual void animateAddRow(FCGridRow row) {
            row.setGrid(this);
            m_rows.add(row);
            row.onAdd();
            if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                int selectedRowsSize = m_selectedRows.size();
                if (selectedRowsSize == 0) {
                    m_selectedRows.add(row);
                    onSelectedRowsChanged();
                }
            }
            if (m_useAnimation) {
                m_animateAddRows.add(row);
            }
        }

        /// <summary>
        /// 动画移除行
        /// </summary>
        /// <param name="row">行</param>
        public virtual void animateRemoveRow(FCGridRow row) {
            if (m_useAnimation) {
                m_animateRemoveRows.add(row);
            }
            else {
                removeRow(row);
            }
        }

        /// <summary>
        /// 开始更新
        /// </summary>
        public virtual void beginUpdate() {
            m_lockUpdate = true;
        }

        /// <summary>
        /// 调用单元格事件
        /// </summary>
        /// <param name="eventName">事件ID</param>
        /// <param name="cell">单元格</param>
        public virtual void callCellEvents(String eventName, FCGridCell cell) {
            if (m_atrEx != null && m_atrEx.m_events != null && m_atrEx.m_events.containsKey(eventName))
            {
                ArrayList<Object> events = m_atrEx.m_events.get(eventName);
                ArrayList<Object> invokes = m_atrEx.m_invokes[eventName];
                int eventSize = events.size();
                for (int i = 0; i < eventSize; i++) {
                    FCGridCellEventCallBack func = events.get(i) as FCGridCellEventCallBack;
                    if (func != null) {
                        func.callGridCellEvent(eventName, this, cell, invokes.get(i));
                    }
                }
            }
        }

        /// <summary>
        /// 调用单元格触摸事件
        /// </summary>
        /// <param name="eventName">事件ID</param>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void callCellTouchEvents(String eventName, FCGridCell cell, FCTouchInfo touchInfo) {
            if (m_atrEx != null && m_atrEx.m_events != null && m_atrEx.m_events.containsKey(eventName))
            {
                ArrayList<Object> events = m_atrEx.m_events.get(eventName);
                ArrayList<Object> invokes = m_atrEx.m_invokes[eventName];
                int eventSize = events.size();
                for (int i = 0; i < eventSize; i++) {
                    FCGridCellTouchEventCallBack func = events.get(i) as FCGridCellTouchEventCallBack;
                    if (func != null) {
                        func.callGridCellTouchEvent(eventName, this, cell, touchInfo, invokes.get(i));
                    }
                }
            }
        }

        /// <summary>
        /// 调用事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="invoke"></param>
        public override void callEvent(String eventName, Object sender, Object invoke) {
            base.callEvent(eventName, getTag(), getTag());
            if (eventName == "onlostfocus" && sender == m_editTextBox) {
                if (m_editTextBox != null && m_editTextBox.getTag() != null) {
                    Object tempVar = m_editTextBox.getTag();
                    onCellEditEnd(tempVar as FCGridCell);
                }
            }
        }

        /// <summary>
        /// 调用事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="invoke"></param>
        public override void callKeyEvent(String eventName, Object sender, char key, Object invoke) {
            base.callKeyEvent(eventName, sender, key, invoke);
            if (key == 13) {
                if (m_editTextBox != null && !m_editTextBox.isMultiline()) {
                    m_editTextBox.setFocused(false);
                }
            } else if (key == 27) {
                onCellEditEnd(null);
            }
        }

        /// <summary>
        /// 请除数据
        /// </summary>
        public virtual void clear() {
            clearRows();
            clearColumns();
        }

        /// <summary>
        /// 清除所有列
        /// </summary>
        public virtual void clearColumns() {
            m_selectedColumns.clear();
            int columnSize = m_columns.size();
            for (int i = 0; i < columnSize; i++) {
                removeView(m_columns.get(i));
                m_columns.get(i).delete();
            }
            m_columns.clear();
        }

        /// <summary>
        /// 清除所有行
        /// </summary>
        public virtual void clearRows() {
            m_hasUnVisibleRow = false;
            m_hoveredCell = null;
            m_hoveredRow = null;
            m_selectedRows.clear();
            m_selectedCells.clear();
            int rowSize = m_rows.size();
            for (int i = 0; i < rowSize; i++) {
                m_rows.get(i).onRemove();
                m_rows.get(i).delete();
            }
            m_rows.clear();
        }

        /// <summary>
        /// 销毁视图的方法
        /// </summary>
        public override void delete() {
            if (!isDeleted()) {
                m_animateAddRows.clear();
                m_animateRemoveRows.clear();
                m_editingCell = null;
                if (m_editTextBox != null) {
                    m_editTextBox.removeEvent(this, "onlostfocus");
                    m_editTextBox.removeEvent(this, "onkeydown");
                }
                stopTimer(m_timerID);
                clear();
            }
            base.delete();
        }

        /// <summary>
        /// 结束更新
        /// </summary>
        public void endUpdate() {
            if (m_lockUpdate) {
                m_lockUpdate = false;
                update();
            }
        }

        /// <summary>
        /// 快速添加列
        /// </summary>
        /// <param name="texts">文字</param>
        public void fastAddColumns(ArrayList<String> texts)
        {
            int textsSize = texts.size();
            for (int i = 0; i < textsSize; i++)
            {
                addColumn(new FCGridColumn(texts.get(i)));
            }
        }

        /// <summary>
        /// 快速添加行
        /// </summary>
        /// <param name="datas">数据</param>
        /// <returns>新的行对象</returns>
        public FCGridRow fastAddRow(ArrayList<String> datas)
        {
            FCGridRow row = new FCGridRow();
            addRow(row);
            int columnsSize = m_columns.size();
            for (int i = 0; i < columnsSize; i++)
            {
                FCGridColumn column = m_columns.get(i);
                String cellType = column.getColumnType();
                FCGridCell cell = null;
                switch (cellType)
                {
                    case "bool":
                        {
                            cell = new FCGridBoolCell();
                            break;
                        }
                    case "button":
                        {
                            cell = new FCGridButtonCell();
                            break;
                        }
                    case "checkbox":
                        {
                            cell = new FCGridCheckBoxCell();
                            break;
                        }
                    case "combobox":
                        {
                            cell = new FCGridComboBoxCell();
                            break;
                        }
                    case "double":
                        {
                            cell = new FCGridDoubleCell();
                            break;
                        }
                    case "float":
                        {
                            cell = new FCGridFloatCell();
                            break;
                        }
                    case "string":
                        {
                            cell = new FCGridStringCell();
                            break;
                        }
                    case "int":
                        {
                            cell = new FCGridIntCell();
                            break;
                        }
                    case "long":
                        {
                            cell = new FCGridLongCell();
                            break;
                        }
                    case "textbox":
                        {
                            cell = new FCGridTextBoxCell();
                            break;
                        }
                    case "percent":
                        {
                            cell = new FCGridPercentCell();
                            break;
                        }
                    default:
                        cell = new FCGridStringCell();
                        break;
                }
                row.addCell(i, cell);
                cell.setString(datas.get(i));
            }
            return row;
        }

        /// <summary>
        /// 获取表格列
        /// </summary>
        /// <param name="columnIndex">列的索引</param>
        /// <returns>表格列</returns>
        public FCGridColumn getColumn(int columnIndex)
        {
            if (columnIndex >= 0 && columnIndex < m_columns.size()) {
                return m_columns.get(columnIndex);
            }
            return null;
        }

        /// <summary>
        /// 获取表格列
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <returns>表格列</returns>
        public FCGridColumn getColumn(String columnName) {
            int columnsSize = m_columns.size();
            for (int i = 0; i < columnsSize; i++) {
                if (m_columns.get(i).getName() == columnName) {
                    return m_columns.get(i);
                }
            }
            return null;
        }

        /// <summary>
        /// 获取所有的列
        /// </summary>
        /// <returns></returns>
        public ArrayList<FCGridColumn> getColumns() {
            return m_columns;
        }

        /// <summary>
        /// 获取内容的高度
        /// </summary>
        /// <returns>高度</returns>
        public override int getContentHeight() {
            int allVisibleRowsHeight = getAllVisibleRowsHeight();
            if (allVisibleRowsHeight > 0) {
                allVisibleRowsHeight += m_headerVisible ? m_headerHeight : 0;
                return allVisibleRowsHeight;
            }
            else {
                return 0;
            }
        }

        /// <summary>
        /// 获取内容的宽度
        /// </summary>
        /// <returns>宽度</returns>
        public override int getContentWidth() {
            return getAllVisibleColumnsWidth();
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns>视图类型</returns>
        public override String getViewType() {
            return "Grid";
        }

        /// <summary>
        /// 获取显示偏移坐标
        /// </summary>
        /// <returns></returns>
        public override FCPoint getDisplayOffset() {
            return new FCPoint(0, 0);
        }

        /// <summary>
        /// 获取事件名称列表
        /// </summary>
        /// <returns>名称列表</returns>
        public override ArrayList<String> getEventNames() {
            ArrayList<String> eventNames = base.getEventNames();
            eventNames.AddRange(new String[] { "GridCellClick", "GridCellEditBegin", "GridCellEditEnd", "GridCellTouchDown", 
            "GridCellTouchMove", "GridCellTouchUp", "GridSelectedCellsChanged", "GridSelectedColumnsChanged", "GridSelectedRowsChanged"});
            return eventNames;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">返回属性值</param>
        /// <param name="type">返回属性类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            switch (name)
            {
                case "allowdragrow":
                    type = "bool";
                    value = FCTran.boolToStr(allowDragRow());
                    break;
                case "allowhoveredrow":
                    type = "bool";
                    value = FCTran.boolToStr(allowHoveredRow());
                    break;
                case "columnsize":
                    type = "int";
                    value = FCTran.intToStr(m_columns.size());
                    break;
                case "celleditmode":
                    {
                        type = "enum:FCGridCellEditMode";
                        FCGridCellEditMode cellEditMode = getCellEditMode();
                        if (cellEditMode == FCGridCellEditMode.DoubleClick)
                        {
                            value = "DoubleClick";
                        }
                        else if (cellEditMode == FCGridCellEditMode.None)
                        {
                            value = "None";
                        }
                        else
                        {
                            value = "SingleClick";
                        }
                        break;
                    }
                case "gridlinecolor":
                    type = "color";
                    value = FCTran.colorToStr(getGridLineColor());
                    break;
                case "headerheight":
                    type = "int";
                    value = FCTran.intToStr(getHeaderHeight());
                    break;
                case "headervisible":
                    type = "bool";
                    value = FCTran.boolToStr(isHeaderVisible());
                    break;
                case "horizontaloffset":
                    type = "int";
                    value = FCTran.intToStr(getHorizontalOffset());
                    break;
                case "multiselect":
                    type = "bool";
                    value = FCTran.boolToStr(multiSelect());
                    break;
                case "selectionmode":
                    {
                        type = "enum:FCGridSelectionMode";
                        FCGridSelectionMode selectionMode = getSelectionMode();
                        if (selectionMode == FCGridSelectionMode.SelectCell)
                        {
                            value = "SelectCell";
                        }
                        else if (selectionMode == FCGridSelectionMode.SelectFullColumn)
                        {
                            value = "SelectFullColumn";
                        }
                        else if (selectionMode == FCGridSelectionMode.SelectFullRow)
                        {
                            value = "SelectFullRow";
                        }
                        else
                        {
                            value = "None";
                        }
                        break;
                    }
                case "useanimation":
                    type = "bool";
                    value = FCTran.boolToStr(useAnimation());
                    break;
                case "verticaloffset":
                    type = "int";
                    value = FCTran.intToStr(getVerticalOffset());
                    break;
                case "rowsize":
                    type = "int";
                    value = FCTran.intToStr(m_rows.size());
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }


        /// <summary>
        /// 获取属性名称列表
        /// </summary>
        /// <returns>属性名称列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "AllowDragRow", "AllowHoveredRow", "CellEditMode", "GridLineColor", "HeaderHeight", "HeaderVisible", "HorizontalOffset", "MultiSelect", 
                "SelectionMode", "UseAnimation", "VerticalOffset"});
            return attributeNames;
        }

        /// <summary>
        /// 根据坐标获取行
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <returns>表格行</returns>
        public FCGridRow getRow(FCPoint mp) {
            int scrollV = 0;
            FCVScrollBar vScrollBar = getVScrollBar();
            if (vScrollBar != null && vScrollBar.isVisible())
            {
                scrollV = -vScrollBar.getPos();
            }
            mp.y -= scrollV;
            if (m_hasUnVisibleRow) {
                int rowsSize = m_rows.size();
                for (int i = 0; i < rowsSize; i++) {
                    FCGridRow row = m_rows.get(i);
                    if (row.isVisible()) {
                        FCRect bounds = row.getBounds();
                        if (mp.y >= bounds.top && mp.y <= bounds.bottom) {
                            return row;
                        }
                    }
                }
            }
            else {
                int begin = 0;
                int end = m_rows.size() - 1;
                int sub = end - begin;
                while (sub >= 0) {
                    int half = begin + sub / 2;
                    FCGridRow row = m_rows.get(half);
                    FCRect bounds = row.getBounds();
                    if (half == begin || half == end) {
                        if (mp.y >= m_rows.get(begin).getBounds().top && mp.y <= m_rows.get(begin).getBounds().bottom) {
                            return m_rows.get(begin);
                        }
                        if (mp.y >= m_rows.get(end).getBounds().top && mp.y <= m_rows.get(end).getBounds().bottom) {
                            return m_rows.get(end);
                        }
                        break;
                    }
                    if (mp.y >= bounds.top && mp.y <= bounds.bottom) {
                        return row;
                    }
                    else if (bounds.top > mp.y) {
                        end = half;
                    }
                    else if (bounds.bottom < mp.y) {
                        begin = half;
                    }
                    sub = end - begin;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取表格行
        /// </summary>
        /// <param name="rowIndex">行的索引</param>
        /// <returns>表格行</returns>
        public FCGridRow getRow(int rowIndex) {
            if (rowIndex >= 0 && rowIndex < m_rows.size()) {
                return m_rows.get(rowIndex);
            }
            return null;
        }

        /// <summary>
        /// 获取所有的行
        /// </summary>
        /// <returns></returns>
        public ArrayList<FCGridRow> getRows() {
            return m_rows;
        }

        /// <summary>
        /// 获取可见的行索引
        /// </summary>
        /// <param name="visiblePercent">可见百分比</param>
        /// <param name="firstVisibleRowIndex">首先可见的行索引</param>
        /// <param name="lastVisibleRowIndex">最后可见的行索引</param>
        public void getVisibleRowsIndex(double visiblePercent, ref int firstVisibleRowIndex, ref int lastVisibleRowIndex) {
            firstVisibleRowIndex = -1;
            lastVisibleRowIndex = -1;
            int rowsSize = m_rows.size();
            if (rowsSize > 0) {
                for (int i = 0; i < rowsSize; i++) {
                    FCGridRow row = m_rows.get(i);
                    if (isRowVisible(row, visiblePercent)) {
                        if (firstVisibleRowIndex == -1) {
                            firstVisibleRowIndex = i;
                        }
                    }
                    else {
                        if (firstVisibleRowIndex != -1) {
                            lastVisibleRowIndex = i;
                            break;
                        }
                    }
                }
                if (firstVisibleRowIndex != -1 && lastVisibleRowIndex == -1) {
                    lastVisibleRowIndex = firstVisibleRowIndex;
                }
            }
        }

        /// <summary>
        /// 插入行
        /// </summary>
        /// <param name="index">索引</param>
        /// <param name="row">行</param>
        public void insertRow(int index, FCGridRow row) {
            row.setGrid(this);
            m_rows.Insert(index, row);
            row.onAdd();
        }

        /// <summary>
        /// 判断行是否可见
        /// </summary>
        /// <param name="row">行</param>
        /// <param name="visiblePercent">可见百分比</param>
        /// <returns>是否可见</returns>
        public bool isRowVisible(FCGridRow row, double visiblePercent) {
            int scrollV = 0;
            FCVScrollBar vScrollBar = getVScrollBar();
            if (vScrollBar != null && vScrollBar.isVisible()) {
                scrollV = -vScrollBar.getPos();
            }
            int cell = (m_headerVisible ? m_headerHeight : 0);
            int floor = getHeight() - cell;
            FCRect bounds = row.getBounds();
            return rowVisible(ref bounds, row.getHeight(), scrollV, visiblePercent, cell, floor);
        }

        /// <summary>
        /// 移动行
        /// </summary>
        /// <param name="oldIndex">旧行</param>
        /// <param name="newIndex">新行</param>
        public virtual void moveRow(int oldIndex, int newIndex) {
            int rowsSize = m_rows.size();
            if (rowsSize > 0) {
                if (oldIndex >= 0 && oldIndex < rowsSize
                    && newIndex >= 0 && newIndex < rowsSize) {
                    FCGridRow movingRow = m_rows.get(oldIndex);
                    FCGridRow targetRow = m_rows.get(newIndex);
                    if (movingRow != targetRow) {
                        //交换行
                        m_rows.set(newIndex, movingRow);
                        m_rows.set(oldIndex, targetRow);
                        movingRow.setIndex(newIndex);
                        targetRow.setIndex(oldIndex);
                        FCVScrollBar vScrollBar = getVScrollBar();
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            int firstVisibleRowIndex = -1, lastVisibleRowIndex = -1;
                            getVisibleRowsIndex(0.6, ref firstVisibleRowIndex, ref lastVisibleRowIndex);
                            int th = targetRow.getHeight();
                            if (newIndex <= firstVisibleRowIndex) {
                                if (newIndex == firstVisibleRowIndex) {
                                    vScrollBar.setPos(vScrollBar.getPos() - th);
                                }
                                int count = 0;
                                while (!isRowVisible(targetRow, 0.6)) {
                                    int newPos = vScrollBar.getPos() - th;
                                    vScrollBar.setPos(newPos);
                                    count++;
                                    if (count > rowsSize || newPos <= vScrollBar.getPos()) {
                                        break;
                                    }
                                }
                            }
                            else if (newIndex >= lastVisibleRowIndex) {
                                if (newIndex == lastVisibleRowIndex) {
                                    vScrollBar.setPos(vScrollBar.getPos() + th);
                                }
                                int count = 0;
                                while (!isRowVisible(targetRow, 0.6)) {
                                    int newPos = vScrollBar.getPos() + th;
                                    vScrollBar.setPos(newPos);
                                    count++;
                                    if (count > rowsSize || newPos >= vScrollBar.getPos()) {
                                        break;
                                    }
                                }
                            }
                            vScrollBar.update();
                        }
                        update();
                    }
                }
            }
        }

        /// <summary>
        /// 单元格触摸点击方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellClick(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcellclick", cell, touchInfo);
        }

        /// <summary>
        /// 单元格编辑开始
        /// </summary>
        /// <param name="cell">单元格</param>
        public virtual void onCellEditBegin(FCGridCell cell) {
            m_editingCell = cell;
            //创建编辑文本框
            if (m_editTextBox == null) {
                FCHost host = getNative().getHost();
                m_editTextBox = host.createInternalView(this, "edittextbox") as FCTextBox;
                m_editTextBox.addEvent(this, "onlostfocus", null);
                m_editTextBox.addEvent(this, "onkeydown", null);
                addView(m_editTextBox);
            }
            m_editTextBox.setFocused(true);
            String text = m_editingCell.getText();
            m_editTextBox.setTag(m_editingCell);
            m_editTextBox.setText(text);
            m_editTextBox.clearRedoUndo();
            m_editTextBox.setVisible(true);
            if (text != null && text.Length > 0) {
                m_editTextBox.setSelectionStart(text.Length);
            }
            callCellEvents("ongridcelleditbegin", cell);
        }

        /// <summary>
        /// 单元格编辑结束
        /// </summary>
        /// <param name="cell">单元格</param>
        public virtual void onCellEditEnd(FCGridCell cell) {
            if (cell != null) {
                cell.setText(m_editTextBox.getText());
            }
            m_editTextBox.setTag(null);
            m_editTextBox.setVisible(false);
            m_editingCell = null;
            callCellEvents("ongridcelleditend", cell);
            invalidate();
        }

        /// <summary>
        /// 单元格触摸按下方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellTouchDown(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcelltouchdown", cell, touchInfo);
        }

        /// <summary>
        /// 单元格触摸进入方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellTouchEnter(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcelltouchenter", cell, touchInfo);
            if (autoEllipsis() || (cell.getStyle() != null && cell.getStyle().autoEllipsis())) {
                m_native.getHost().showToolTip(cell.getPaintText(), m_native.getTouchPoint());
            }
        }

        /// <summary>
        /// 单元格触摸移出方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellTouchLeave(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcelltouchleave", cell, touchInfo);
        }

        /// <summary>
        /// 单元格触摸移动方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellTouchMove(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcelltouchmove", cell, touchInfo);
        }

        /// <summary>
        /// 单元格触摸抬起方法
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="touchInfo">触摸信息</param>
        public virtual void onCellTouchUp(FCGridCell cell, FCTouchInfo touchInfo) {
            callCellTouchEvents("ongridcelltouchup", cell, touchInfo);
        }

        /// <summary>
        /// 复制文字
        /// </summary>
        public override void onCopy()
        {
            ArrayList<FCGridCell> selectedCells = getSelectedCells();
            int selectedCellsSize = selectedCells.Count;
            if (selectedCellsSize > 0)
            {
                String selectionText = selectedCells.get(0).getString();
                if (selectionText != null && selectionText.Length > 0)
                {
                    FCHost host = getNative().getHost();
                    host.copy(selectionText);
                    base.onCopy();
                }
            }
        }

        /// <summary>
        /// 拖动滚动许可检查
        /// </summary>
        /// <returns></returns>
        public override bool onDragScrollPermit()
        {
            if (m_editingCell != null || m_editingRow != null)
            {
                return false;
            }
            return base.onDragScrollPermit();
        }

        /// <summary>
        /// 行拖动结束事件
        /// </summary>
        public virtual void onRowDraged()
        {
            callEvents("ongridrowdraged");
        }

        /// <summary>
        /// 键盘方法
        /// </summary>
        /// <param name="key">键盘参数</param>
        public override void onKeyDown(char key) {
            FCHost host = getNative().getHost();
            if (!host.isKeyPress(0x10) && !host.isKeyPress(0x11) && !host.isKeyPress(0x12)) {
                if (key == 38 || key == 40) {
                    callKeyEvents("onkeydown", key);
                    FCGridRow row = null;
                    int offset = 0;
                    if (key == 38) {
                        row = selectFrontRow();
                        if (row != null) {
                            offset = -row.getHeight();
                        }
                    }
                    else if (key == 40) {
                        row = selectNextRow();
                        if (row != null) {
                            offset = row.getHeight();
                        }
                    }
                    if (row != null && !isRowVisible(row, 0.6)) {
                        FCVScrollBar vScrollBar = getVScrollBar();
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            vScrollBar.setPos(vScrollBar.getPos() + offset);
                            vScrollBar.update();
                        }
                        onSelectedRowsChanged();
                    }
                    invalidate();
                    return;
                }
            }
            base.onKeyDown(key);
        }

        /// <summary>
        /// 视图添加方法
        /// </summary>
        public override void onLoad() {
            base.onAdd();
            if (m_useAnimation) {
                startTimer(m_timerID, 20);
            }
            else {
                stopTimer(m_timerID);
            }
        }

        /// <summary>
        /// 丢失焦点方法
        /// </summary>
        public override void onLostFocus() {
            base.onLostFocus();
            m_hoveredCell = null;
            m_hoveredRow = null;
        }

        /// <summary>
        /// 触摸按下方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchDown(FCTouchInfo touchInfo) {
            base.onTouchDown(touchInfo);
            touchEvent(touchInfo, 1);
        }

        /// <summary>
        /// 触摸离开方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchLeave(FCTouchInfo touchInfo) {
            base.onTouchLeave(touchInfo);
            if (m_hoveredCell != null) {
                onCellTouchLeave(m_hoveredCell, touchInfo);
                m_hoveredCell = null;
            }
            m_hoveredRow = null;
            invalidate();
        }

        /// <summary>
        /// 触摸移动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchMove(FCTouchInfo touchInfo) {
            base.onTouchMove(touchInfo);
            touchEvent(touchInfo, 0);
        }

        /// <summary>
        /// 触摸抬起方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchUp(FCTouchInfo touchInfo) {
            base.onTouchUp(touchInfo);
            touchEvent(touchInfo, 2);
        }

        /// <summary>
        /// 重绘前景方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaintForeground(FCPaint paint, FCRect clipRect) {
            resetHeaderLayout();
            int width = getWidth(), height = getHeight();
            if (width > 0 && height > 0) {
                FCNative native = getNative();
                FCRect drawRect = new FCRect(0, 0, width, height);
                int allVisibleColumnsWidth = getAllVisibleColumnsWidth();
                //行的可见宽度
                int rowVisibleWidth = 0;
                if (allVisibleColumnsWidth > 0) {
                    rowVisibleWidth = allVisibleColumnsWidth > width ? width : allVisibleColumnsWidth;
                }
                //绘制标题头
                int hHeight = m_headerVisible ? m_headerHeight : 0;
                int scrollH = 0, scrollV = 0;
                FCHScrollBar hScrollBar = getHScrollBar();
                FCVScrollBar vScrollBar = getVScrollBar();
                if (hScrollBar != null && hScrollBar.isVisible()) {
                    scrollH = -hScrollBar.getPos();
                }
                if (vScrollBar != null && vScrollBar.isVisible()) {
                    scrollV = -vScrollBar.getPos();
                }
                onSetEmptyClipRegion();
                //获取显示的第一行和最后一行
                FCPoint fPoint = new FCPoint(0, hHeight + 1);
                FCPoint ePoint = new FCPoint(0, height - 10);
                FCGridRow fRow = getRow(fPoint);
                FCGridRow eRow = getRow(ePoint);
                while (eRow == null && ePoint.y > 0) {
                    ePoint.y -= 10;
                    eRow = getRow(ePoint);
                }
                if (fRow != null && eRow != null) {
                    int fIndex = fRow.getIndex();
                    int eIndex = eRow.getIndex();
                    for (int i = fIndex; i <= eIndex; i++) {
                        FCGridRow row = m_rows.get(i);
                        if (row.isVisible()) {
                            FCRect rowRect = row.getBounds();
                            rowRect.top += scrollV;
                            rowRect.bottom += scrollV;
                            row.onPaint(paint, rowRect, row.getVisibleIndex() % 2 == 1);
                            //画选中行
                            FCRect tempRect = new FCRect();
                            ArrayList<FCGridCell> cells = null;
                            ArrayList<FCGridCell> frozenCells = new ArrayList<FCGridCell>();
                            for (int j = 0; j < 2; j++) {
                                if (j == 0) {
                                    cells = row.getCells();
                                }
                                else {
                                    cells = frozenCells;
                                }
                                int frozenRight = 0;
                                int cellSize = cells.size();
                                for (int c = 0; c < cellSize; c++) {
                                    FCGridCell cell = cells.get(c);
                                    FCGridColumn column = cell.getColumn();
                                    if (column != null && column.isVisible())
                                    {
                                        FCRect headerRect = column.getHeaderRect();
                                        if (j == 0 && column.isFrozen()) {
                                            frozenRight = headerRect.right;
                                            frozenCells.add(cell);
                                            continue;
                                        }
                                        if (!column.isFrozen()) {
                                            headerRect.left += scrollH;
                                            headerRect.right += scrollH;
                                        }
                                        int cellWidth = column.getWidth();
                                        int colSpan = cell.getColSpan();
                                        if (colSpan > 1) {
                                            for (int n = 1; n < colSpan; n++) {
                                                FCGridColumn spanColumn = getColumn(column.getIndex() + n);
                                                if (spanColumn != null && spanColumn.isVisible()) {
                                                    cellWidth += spanColumn.getWidth();
                                                }
                                            }
                                        }
                                        int cellHeight = row.getHeight();
                                        int rowSpan = cell.getRowSpan();
                                        if (rowSpan > 1) {
                                            for (int n = 1; n < rowSpan; n++) {
                                                FCGridRow spanRow = getRow(i + n);
                                                if (spanRow != null && spanRow.isVisible()) {
                                                    cellHeight += spanRow.getHeight();
                                                }
                                            }
                                        }
                                        FCRect cellRect = new FCRect(headerRect.left, rowRect.top + m_verticalOffset, headerRect.left + cellWidth, rowRect.top + m_verticalOffset + cellHeight);
                                        cellRect.left += row.getHorizontalOffset();
                                        cellRect.right += row.getHorizontalOffset();
                                        if (native.getHost().getIntersectRect(ref tempRect, ref cellRect, ref drawRect) > 0) {
                                            if (cell != null) {
                                                FCRect cellClipRect = cellRect;
                                                if (!column.isFrozen()) {
                                                    if (cellClipRect.left < frozenRight) {
                                                        cellClipRect.left = frozenRight;
                                                    }
                                                    if (cellClipRect.right < frozenRight) {
                                                        cellClipRect.right = frozenRight;
                                                    }
                                                }
                                                //cellRect.left -= 1;
                                                cell.onPaint(paint, cellRect, cellClipRect, row.getVisibleIndex() % 2 == 1);
                                                if (m_editingCell != null && m_editingCell == cell && m_editTextBox != null) {
                                                    FCRect editClipRect = new FCRect(cellClipRect.left - cellRect.left, cellClipRect.top - cellRect.top,
                                                        cellClipRect.right - cellRect.left, cellClipRect.bottom - cellRect.top);
                                                    onPaintEditTextBox(cell, paint, cellRect, editClipRect);
                                                }
                                                if (m_gridLineColor != FCColor.None) {
                                                    if (i == fIndex) {
                                                        paint.drawLine(m_gridLineColor, 1, 0, cellClipRect.left, cellClipRect.top, cellClipRect.right - 1, cellClipRect.top);
                                                    }
                                                    if (c == 0) {
                                                        paint.drawLine(m_gridLineColor, 1, 0, cellClipRect.left, cellClipRect.top, cellClipRect.left, cellClipRect.bottom - 1);
                                                    }
                                                    paint.drawLine(m_gridLineColor, 1, 0, cellClipRect.left, cellClipRect.bottom - 1, cellClipRect.right - 1, cellClipRect.bottom - 1);
                                                    paint.drawLine(m_gridLineColor, 1, 0, cellClipRect.right - 1, cellClipRect.top, cellClipRect.right - 1, cellClipRect.bottom - 1);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            frozenCells.clear();
                            row.onPaintBorder(paint, rowRect, row.getVisibleIndex() % 2 == 1);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 绘制编辑文本框
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="paint">绘图对象</param>
        /// <param name="rect">区域</param>
        /// <param name="clipRect">裁剪区域</param>
        public virtual void onPaintEditTextBox(FCGridCell cell, FCPaint paint, FCRect rect, FCRect clipRect) {
            m_editTextBox.setRegion(clipRect);
            m_editTextBox.setBounds(rect);
            m_editTextBox.setDisplayOffset(false);
            m_editTextBox.bringToFront();
        }

        /// <summary>
        /// 行编辑开始
        /// </summary>
        /// <param name="row">行</param>
        public virtual void onRowEditBegin(FCGridRow row) {
            FCView editButton = row.getEditButton();
            if (editButton != null && !containsView(editButton)) {
                FCPoint mp = getTouchPoint();
                if (mp.x - m_touchDownPoint.x < -10 && Math.Abs(mp.y - m_touchDownPoint.y) < 30) {
                    m_editingRow = row;
                    addView(editButton);
                    if (m_useAnimation) {
                        editButton.setLocation(new FCPoint(-10000, -10000));
                        m_editingRow.m_editState = 1;
                    }
                    else {
                        m_editingRow.setHorizontalOffset(m_editingRow.getHorizontalOffset() - editButton.getWidth() - ((m_vScrollBar != null && m_vScrollBar.isVisible()) ? m_vScrollBar.getWidth() : 0));
                    }
                }
            }
        }

        /// <summary>
        /// 行编辑结束
        /// </summary>
        public virtual void onRowEditEnd() {
            if (m_useAnimation) {
                m_editingRow.m_editState = 2;
            } else {
                m_editingRow.setHorizontalOffset(0);
                removeView(m_editingRow.getEditButton());
                m_editingRow = null;
            }
        }

        /// <summary>
        /// 缩放
        /// </summary>
        /// <param name="scaleFactorX">横向比例</param>
        /// <param name="scaleFactorY">纵向比例</param>
        public override void onScaling(double scaleFactorX, double scaleFactorY) {
            m_headerHeight = (int)(m_headerHeight * scaleFactorY);
            base.onScaling(scaleFactorX, scaleFactorY);
            if (m_rowStyle != null) {
                m_rowStyle.m_font.m_fontSize = (float)(m_rowStyle.m_font.m_fontSize * (scaleFactorX + scaleFactorY) / 2);
            }
            if (m_alternateRowStyle != null) {
                m_alternateRowStyle.m_font.m_fontSize = (float)(m_alternateRowStyle.m_font.m_fontSize * (scaleFactorX + scaleFactorY) / 2);
            }
            int rowsSize = m_rows.size();
            for (int i = 0; i < rowsSize; i++) {
                m_rows.get(i).onScaling(scaleFactorX, scaleFactorY);
            }
        }

        /// <summary>
        /// 选中单元格改变方法
        /// </summary>
        public virtual void onSelectedCellsChanged() {
            callEvents("ongridselectedcellschanged");
        }

        /// <summary>
        /// 选中列改变方法
        /// </summary>
        public virtual void onSelectedColumnsChanged() {
            callEvents("ongridselectedcolumnschanged");
        }

        /// <summary>
        /// 选中行改变方法
        /// </summary>
        public virtual void onSelectedRowsChanged() {
            callEvents("ongridselectedrowschanged");
        }

        /// <summary>
        /// 设置视图不可见方法
        /// </summary>
        public virtual void onSetEmptyClipRegion() {
            //隐藏视图
            ArrayList<FCView> views = m_views;
            int viewsSize = views.size();
            FCRect emptyClipRect = new FCRect();
            for (int i = 0; i < viewsSize; i++) {
                FCView view = views.get(i);
                if (m_editingRow != null && view == m_editingRow.getEditButton()) {
                    continue;
                }
                FCScrollBar scrollBar = view as FCScrollBar;
                FCGridColumn gridColumn = view as FCGridColumn;
                if (view != m_editTextBox && scrollBar == null && gridColumn == null) {
                    view.setRegion(emptyClipRect);
                }
            }
        }

        /// <summary>
        /// 秒表方法
        /// </summary>
        /// <param name="timerID">秒表ID</param>
        public override void onTimer(int timerID) {
            base.onTimer(timerID);
            if (m_timerID == timerID) {
                if (m_useAnimation) {
                    bool paint = false;
                    if (m_horizontalOffset != 0 || m_verticalOffset != 0) {
                        if (m_horizontalOffset != 0) {
                            m_horizontalOffset = m_horizontalOffset * 2 / 3;
                            if (m_horizontalOffset >= -1 && m_horizontalOffset <= 1) {
                                m_horizontalOffset = 0;
                            }
                        }
                        if (m_verticalOffset != 0) {
                            m_verticalOffset = m_verticalOffset * 2 / 3;
                            if (m_verticalOffset >= -1 && m_verticalOffset <= 1) {
                                m_verticalOffset = 0;
                            }
                        }
                        paint = true;
                    }
                    int animateAddRowsSize = m_animateAddRows.size();
                    if (animateAddRowsSize > 0) {
                        int width = getAllVisibleColumnsWidth();
                        int step = width / 10;
                        if (step < 10) {
                            step = 10;
                        }
                        for (int i = 0; i < animateAddRowsSize; i++) {
                            FCGridRow row = m_animateAddRows.get(i);
                            int horizontalOffset = row.getHorizontalOffset();
                            if (horizontalOffset > step) {
                                horizontalOffset -= step;
                            }
                            else {
                                horizontalOffset = 0;
                            }
                            row.setHorizontalOffset(horizontalOffset);
                            if (horizontalOffset == 0) {
                                m_animateAddRows.removeAt(i);
                                animateAddRowsSize--;
                                i--;
                            }
                        }
                        paint = true;
                    }
                    int animateRemoveRowsSize = m_animateRemoveRows.size();
                    if (animateRemoveRowsSize > 0) {
                        int width = getAllVisibleColumnsWidth();
                        int step = width / 10;
                        if (step < 10) {
                            step = 10;
                        }
                        for (int i = 0; i < animateRemoveRowsSize; i++) {
                            FCGridRow row = m_animateRemoveRows.get(i);
                            int horizontalOffset = row.getHorizontalOffset();
                            if (horizontalOffset <= width) {
                                horizontalOffset += step;
                            }
                            row.setHorizontalOffset(horizontalOffset);
                            if (horizontalOffset > width) {
                                m_animateRemoveRows.removeAt(i);
                                removeRow(row);
                                update();
                                animateRemoveRowsSize--;
                                i--;
                            }
                        }
                        paint = true;
                    }
                    if (m_editingRow != null) {
                        int scrollH = 0, scrollV = 0;
                        FCHScrollBar hScrollBar = getHScrollBar();
                        FCVScrollBar vScrollBar = getVScrollBar();
                        int vScrollBarW = 0;
                        if (hScrollBar != null && hScrollBar.isVisible()) {
                            scrollH = -hScrollBar.getPos();
                        }
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            scrollV = -vScrollBar.getPos();
                            vScrollBarW = vScrollBar.getWidth();
                        }
                        if (m_editingRow.m_editState == 1) {
                            FCView editButton = m_editingRow.getEditButton();
                            bool isOver = false;
                            int sub = editButton.getWidth() + vScrollBarW + m_editingRow.getHorizontalOffset();
                            if (sub < 2) {
                                isOver = true;
                                m_editingRow.setHorizontalOffset(-editButton.getWidth() - vScrollBarW);
                            }
                            else {
                                m_editingRow.setHorizontalOffset(m_editingRow.getHorizontalOffset() - 10);
                            }
                            editButton.setLocation(new FCPoint(getAllVisibleColumnsWidth() + scrollH + m_editingRow.getHorizontalOffset(),
                            m_editingRow.getBounds().top + scrollV));
                            if (isOver) {
                                m_editingRow.m_editState = 0;
                            }
                        }
                        if (m_editingRow.m_editState == 2) {
                            FCView editButton = m_editingRow.getEditButton();
                            bool isOver = false;
                            if (m_editingRow.getHorizontalOffset() < 0) {
                                m_editingRow.setHorizontalOffset(m_editingRow.getHorizontalOffset() + 10);
                                if (m_editingRow.getHorizontalOffset() >= 0) {
                                    m_editingRow.setHorizontalOffset(0);
                                    isOver = true;
                                }
                            }
                            editButton.setLocation(new FCPoint(getAllVisibleColumnsWidth() + scrollH + m_editingRow.getHorizontalOffset(),
                            m_editingRow.getBounds().top + scrollV));
                            if (isOver) {
                                removeView(editButton);
                                m_editingRow.m_editState = 0;
                                m_editingRow = null;
                            }
                        }
                        paint = true;
                    }
                    if (paint) {
                        invalidate();
                    }
                }
            }
        }

        /// <summary>
        /// 可见状态改变方法
        /// </summary>
        public override void onVisibleChanged() {
            base.onVisibleChanged();
            m_hoveredCell = null;
            m_hoveredRow = null;
        }

        /// <summary>
        /// 移除列
        /// </summary>
        /// <param name="column">列</param>
        public virtual void removeColumn(FCGridColumn column) {
            bool selectedChanged = false;
            int selectedColumnsSize = m_selectedColumns.size();
            for (int i = 0; i < selectedColumnsSize; i++) {
                if (m_selectedColumns.get(i) == column) {
                    m_selectedColumns.remove(column);
                    selectedChanged = true;
                    break;
                }
            }
            m_columns.remove(column);
            int columnsSize = m_columns.size();
            for (int i = 0; i < columnsSize; i++) {
                m_columns.get(i).setIndex(i);
            }
            removeView(column);
            int rowSize = m_rows.size();
            for (int i = 0; i < rowSize; i++) {
                FCGridRow row = m_rows.get(i);
                row.removeCell(column.getIndex());
            }
            if (selectedChanged) {
                onSelectedColumnsChanged();
            }
        }

        /// <summary>
        /// 移除行
        /// </summary>
        /// <param name="row">行</param>
        public void removeRow(FCGridRow row) {
            if (m_editingRow != null) {
                if (containsView(m_editingRow.getEditButton())) {
                    removeView(m_editingRow.getEditButton());
                }
                m_editingRow.m_editState = 0;
                m_editingRow = null;
            }
            if (m_animateAddRows.Contains(row)) {
                m_animateAddRows.remove(row);
            }
            bool selectedChanged = false;
            bool selected = false;
            int selectedRowsSize = (int)m_selectedRows.size();
            for (int i = 0; i < selectedRowsSize; i++) {
                FCGridRow selectedRow = m_selectedRows.get(i);
                if (selectedRow == row) {
                    selected = true;
                    break;
                }
            }
            if (selected) {
                if (row.getIndex() == 0)
                {
                    FCGridRow otherRow = selectNextRow();
                    if (otherRow != null)
                    {
                        selectedChanged = true;
                    }
                    else
                    {
                        otherRow = selectFrontRow();
                        if (otherRow != null)
                        {
                            selectedChanged = true;
                        }
                    }
                }
                else
                {
                    FCGridRow otherRow = selectFrontRow();
                    if (otherRow != null)
                    {
                        selectedChanged = true;
                    }
                    else
                    {
                        otherRow = selectNextRow();
                        if (otherRow != null)
                        {
                            selectedChanged = true;
                        }
                    }
                }
            }
            if (m_hoveredRow == row) {
                m_hoveredCell = null;
                m_hoveredRow = null;
            }
            row.onRemove();
            m_rows.remove(row);
            int rowSize = m_rows.size();
            if (rowSize == 0) {
                m_selectedCells.clear();
                m_selectedRows.clear();
            }
            int visibleIndex = 0;
            for (int i = 0; i < rowSize; i++) {
                FCGridRow gridRow = m_rows.get(i);
                gridRow.setIndex(i);
                if (gridRow.isVisible()) {
                    gridRow.setVisibleIndex(visibleIndex);
                    visibleIndex++;
                }
            }
            if (selected) {
                if (selectedChanged) {
                    onSelectedRowsChanged();
                }
                else {
                    m_selectedCells.clear();
                    m_selectedRows.clear();
                }
            }
        }

        /// <summary>
        /// 调整列的布局
        /// </summary>
        public virtual void resetHeaderLayout() {
            if (!m_lockUpdate) {
                int left = 0, top = 0;
                int scrollH = 0, scrollV = 0;
                FCHScrollBar hScrollBar = getHScrollBar();
                FCVScrollBar vScrollBar = getVScrollBar();
                int vScrollBarW = 0;
                if (hScrollBar != null && hScrollBar.isVisible()) {
                    scrollH = -hScrollBar.getPos();
                }
                if (vScrollBar != null && vScrollBar.isVisible()) {
                    scrollV = -vScrollBar.getPos();
                    vScrollBarW = vScrollBar.getWidth();
                }
                int headerHeight = m_headerVisible ? m_headerHeight : 0;
                //计算列的区域
                FCGridColumn draggingColumn = null;
                int columnSize = m_columns.size();
                for (int i = 0; i < columnSize; i++) {
                    FCGridColumn column = m_columns.get(i);
                    if (column.isVisible()) {
                        FCRect cellRect = new FCRect(left + m_horizontalOffset, top + m_verticalOffset,
                        left + m_horizontalOffset + column.getWidth(), top + headerHeight + m_verticalOffset);
                        column.setHeaderRect(cellRect);
                        if (column.isDragging()) {
                            draggingColumn = column;
                            column.setBounds(new FCRect(column.getLeft(), cellRect.top, column.getRight(), cellRect.bottom));
                        }
                        else {
                            if (!column.isFrozen()) {
                                cellRect.left += scrollH;
                                cellRect.right += scrollH;
                            }
                            column.setBounds(cellRect);
                        }
                        left += column.getWidth();
                    }
                }
                //将视图置于最前
                for (int i = columnSize - 1; i >= 0; i--) {
                    m_columns.get(i).bringToFront();
                }
                if (draggingColumn != null) {
                    draggingColumn.bringToFront();
                }
                if (m_editingRow != null && m_editingRow.m_editState == 0 && m_editingRow.getEditButton() != null) {
                    FCView editButton = m_editingRow.getEditButton();
                    editButton.setLocation(new FCPoint(getAllVisibleColumnsWidth() - editButton.getWidth() + scrollH - vScrollBarW, m_editingRow.getBounds().top + scrollV));
                }
            }
        }

        /// <summary>
        /// 行是否可见
        /// </summary>
        /// <param name="bounds"></param>
        /// <param name="rowHeight"></param>
        /// <param name="scrollV"></param>
        /// <param name="visiblePercent"></param>
        /// <param name="cell"></param>
        /// <param name="floor"></param>
        /// <returns></returns>
        public virtual bool rowVisible(ref FCRect bounds, int rowHeight, int scrollV, double visiblePercent, int cell, int floor) {
            int rowtop = bounds.top + scrollV;
            int rowbottom = bounds.bottom + scrollV;
            if (rowtop < cell) {
                rowtop = cell;
            }
            else if (rowtop > floor) {
                rowtop = floor;
            }
            if (rowbottom < cell) {
                rowbottom = cell;
            }
            else if (rowbottom > floor) {
                rowbottom = floor;
            }
            if (rowbottom - rowtop >= (int)(rowHeight * visiblePercent)) {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 选中上一行
        /// </summary>
        public FCGridRow selectFrontRow() {
            int rowsSize = m_rows.size();
            if (rowsSize == 0) {
                m_selectedRows.clear();
                m_selectedCells.clear();
                return null;
            }
            FCGridRow frontRow = null;
            ArrayList<FCGridRow> selectedRows = getSelectedRows();
            if (selectedRows.size() == 1) {
                //获取向上的行
                FCGridRow selectedRow = selectedRows.get(0);
                int selectedIndex = selectedRow.getIndex();
                for (int i = selectedIndex - 1; i >= 0; i--) {
                    if (i < rowsSize && m_rows.get(i).isVisible()) {
                        frontRow = m_rows.get(i);
                        break;
                    }
                }
                //向上
                if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                    if (frontRow != null) {
                        m_selectedRows.clear();
                        m_selectedCells.clear();
                        m_selectedRows.add(frontRow);
                        onSelectedRowsChanged();
                    }
                    else {
                        m_selectedRows.clear();
                        m_selectedCells.clear();
                        frontRow = m_rows.get(m_rows.size() - 1);
                        m_selectedRows.add(frontRow);
                        FCVScrollBar vScrollBar = getVScrollBar();
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            vScrollBar.scrollToEnd();
                        }
                        onSelectedRowsChanged();
                    }
                }
            }
            return frontRow;
        }

        /// <summary>
        /// 选中第一行
        /// </summary>
        public FCGridRow selectFirstRow() {
            int rowsSize = m_rows.size();
            if (rowsSize == 0) {
                m_selectedRows.clear();
                m_selectedCells.clear();
                return null;
            }
            for (int i = 0; i < rowsSize; i++)
            {
                FCGridRow firstRow = m_rows.get(i);
                if (firstRow.isVisible())
                {
                    m_selectedRows.clear();
                    m_selectedCells.clear();
                    m_selectedRows.add(firstRow);
                    FCVScrollBar vScrollBar = getVScrollBar();
                    if (vScrollBar != null && vScrollBar.isVisible())
                    {
                        vScrollBar.scrollToBegin();
                    }
                    onSelectedRowsChanged();
                    return firstRow;
                }
            }
            return null;
        }

        /// <summary>
        /// 选中最后一行
        /// </summary>
        /// <returns></returns>
        public FCGridRow selectLastRow() {
            int rowsSize = m_rows.size();
            if (rowsSize == 0) {
                m_selectedRows.clear();
                m_selectedCells.clear();
                return null;
            }
            for (int i = rowsSize - 1; i >= 0; i--)
            {
                FCGridRow lastRow = m_rows.get(i);
                if (lastRow.isVisible())
                {
                    m_selectedRows.clear();
                    m_selectedCells.clear();
                    m_selectedRows.add(lastRow);
                    FCVScrollBar vScrollBar = getVScrollBar();
                    if (vScrollBar != null && vScrollBar.isVisible())
                    {
                        vScrollBar.scrollToEnd();
                    }
                    onSelectedRowsChanged();
                    return lastRow;
                }
            }
            return null;
        }

        /// <summary>
        /// 选中下一行
        /// </summary>
        public FCGridRow selectNextRow() {
            int rowsSize = m_rows.size();
            if (rowsSize == 0) {
                m_selectedRows.clear();
                m_selectedCells.clear();
                return null;
            }
            FCGridRow nextRow = null;
            ArrayList<FCGridRow> selectedRows = getSelectedRows();
            if (selectedRows.size() == 1) {
                FCGridRow selectedRow = selectedRows.get(0);
                int selectedIndex = selectedRow.getIndex();
                for (int i = selectedIndex + 1; i < rowsSize; i++) {
                    if (i >= 0 && m_rows.get(i).isVisible()) {
                        nextRow = m_rows.get(i);
                        break;
                    }
                }
                //向下
                if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                    if (nextRow != null) {
                        m_selectedRows.clear();
                        m_selectedCells.clear();
                        m_selectedRows.add(nextRow);
                        onSelectedRowsChanged();
                    }
                    else {
                        m_selectedRows.clear();
                        m_selectedCells.clear();
                        nextRow = m_rows.get(0);
                        m_selectedRows.add(nextRow);
                        FCVScrollBar vScrollBar = getVScrollBar();
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            vScrollBar.scrollToBegin();
                        }
                        onSelectedRowsChanged();
                    }
                }
            }
            return nextRow;
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value)
        {
            switch (name)
            {
                case "allowdragrow":
                    setAllowDragRow(FCTran.strToBool(value));
                    break;
                case "allowhoveredrow":
                    setAllowHoveredRow(FCTran.strToBool(value));
                    break;
                case "celleditmode":
                    {
                        value = value.ToLower();
                        if (value == "doubleclick")
                        {
                            setCellEditMode(FCGridCellEditMode.DoubleClick);
                        }
                        else if (value == "none")
                        {
                            setCellEditMode(FCGridCellEditMode.None);
                        }
                        else if (value == "singleclick")
                        {
                            setCellEditMode(FCGridCellEditMode.SingleClick);
                        }
                        break;
                    }
                case "gridlinecolor":
                    setGridLineColor(FCTran.strToColor(value));
                    break;
                case "headerheight":
                    setHeaderHeight(FCTran.strToInt(value));
                    break;
                case "headervisible":
                    setHeaderVisible(FCTran.strToBool(value));
                    break;
                case "horizontaloffset":
                    setHorizontalOffset(FCTran.strToInt(value));
                    break;
                case "multiselect":
                    setMultiSelect(FCTran.strToBool(value));
                    break;
                case "selectionmode":
                    {
                        value = value.ToLower();
                        if (value == "selectcell")
                        {
                            setSelectionMode(FCGridSelectionMode.SelectCell);
                        }
                        else if (value == "selectfullcolumn")
                        {
                            setSelectionMode(FCGridSelectionMode.SelectFullColumn);
                        }
                        else if (value == "selectfullrow")
                        {
                            setSelectionMode(FCGridSelectionMode.SelectFullRow);
                        }
                        else
                        {
                            setSelectionMode(FCGridSelectionMode.SelectNone);
                        }
                        break;
                    }
                case "useanimation":
                    setUseAnimation(FCTran.strToBool(value));
                    break;
                case "verticaloffset":
                    setVerticalOffset(FCTran.strToInt(value));
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="grid">表格</param>
        /// <param name="column">列</param>
        /// <param name="sortMode">排序方式</param>
        public virtual void sortColumn(FCGrid grid, FCGridColumn column, FCGridColumnSortMode sortMode) {
            if (column.allowSort()) {
                //取消原有排序
                int colSize = grid.m_columns.size();
                for (int i = 0; i < colSize; i++) {
                    if (grid.m_columns.get(i) != column) {
                        grid.m_columns.get(i).setSortMode(FCGridColumnSortMode.None);
                    }
                    else {
                        grid.m_columns.get(i).setSortMode(sortMode);
                    }
                }
                //重新排序，要改成二叉树排序
                if (m_sort != null) {
                    m_sort.sortColumn(this, column, sortMode);
                }
                grid.update();
                grid.invalidate();
            }
        }

        /// <summary>
        /// 触摸事件
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        /// <param name="state">0:移动 1:按下 2:抬起</param>
        public virtual void touchEvent(FCTouchInfo touchInfo, int state) {
            FCPoint mp = touchInfo.m_firstPoint;
            int height = getHeight();
            int hHeight = m_headerVisible ? m_headerHeight : 0;
            int scrollH = 0, scrollV = 0;
            FCHost host = getNative().getHost();
            FCHScrollBar hScrollBar = getHScrollBar();
            FCVScrollBar vScrollBar = getVScrollBar();
            int vLineSize = 0;
            if (hScrollBar != null && hScrollBar.isVisible())
            {
                scrollH = -hScrollBar.getPos();
            }
            if (vScrollBar != null && vScrollBar.isVisible())
            {
                scrollV = -vScrollBar.getPos();
                vLineSize = vScrollBar.getLineSize();
            }
            FCPoint fPoint = new FCPoint(0, hHeight + 1);
            FCPoint ePoint = new FCPoint(0, height - 10 + vLineSize);
            FCGridRow fRow = getRow(fPoint);
            FCGridRow eRow = getRow(ePoint);
            while (eRow == null && ePoint.y > 0) {
                ePoint.y -= 10;
                eRow = getRow(ePoint);
            }
            if (fRow != null && eRow != null) {
                int fIndex = fRow.getIndex();
                int eIndex = eRow.getIndex();
                for (int i = fIndex; i <= eIndex; i++) {
                    FCGridRow row = m_rows.get(i);
                    if (row.isVisible()) {
                        FCRect rowRect = row.getBounds();
                        rowRect.top += scrollV;
                        rowRect.bottom += scrollV;
                        ArrayList<FCGridCell> cells = null;
                        ArrayList<FCGridCell> unFrozenCells = new ArrayList<FCGridCell>();
                        for (int j = 0; j < 2; j++) {
                            if (j == 0) {
                                cells = row.getCells();
                            }
                            else {
                                cells = unFrozenCells;
                            }
                            int cellSize = cells.size();
                            for (int c = 0; c < cellSize; c++) {
                                FCGridCell cell = cells.get(c);
                                FCGridColumn column = cell.getColumn();
                                if (column != null && column.isVisible())
                                {
                                    if (j == 0 && !column.isFrozen()) {
                                        unFrozenCells.add(cell);
                                        continue;
                                    }
                                    //获取单元格的矩形
                                    FCRect headerRect = column.getHeaderRect();
                                    if (!column.isFrozen()) {
                                        headerRect.left += scrollH;
                                        headerRect.right += scrollH;
                                    }
                                    int cellWidth = column.getWidth();
                                    int colSpan = cell.getColSpan();
                                    if (colSpan > 1) {
                                        for (int n = 1; n < colSpan; n++) {
                                            FCGridColumn spanColumn = getColumn(column.getIndex() + n);
                                            if (spanColumn != null && spanColumn.isVisible()) {
                                                cellWidth += spanColumn.getWidth();
                                            }
                                        }
                                    }
                                    int cellHeight = row.getHeight();
                                    int rowSpan = cell.getRowSpan();
                                    if (rowSpan > 1) {
                                        for (int n = 1; n < rowSpan; n++) {
                                            FCGridRow spanRow = getRow(i + n);
                                            if (spanRow != null && spanRow.isVisible()) {
                                                cellHeight += spanRow.getHeight();
                                            }
                                        }
                                    }
                                    FCRect cellRect = new FCRect(headerRect.left, rowRect.top + m_verticalOffset, headerRect.left + cellWidth, rowRect.top + m_verticalOffset + cellHeight);
                                    if (mp.x >= cellRect.left && mp.x <= cellRect.right && mp.y >= cellRect.top && mp.y <= cellRect.bottom) {
                                        if (state == 0) {
                                            bool hoverChanged = false;
                                            if (m_allowHoveredRow && m_hoveredRow != row) {
                                                m_hoveredRow = row;
                                                hoverChanged = true;
                                            }
                                            if (getNative().getPushedView() == this) {
                                                if (m_allowDragRow && column.allowDragRow())
                                                {
                                                    m_readyToDragScroll = false; 
                                                    if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                                                        int selectedRowsSize = m_selectedRows.size();
                                                        if (selectedRowsSize == 1) {
                                                            if (m_selectedRows.get(0) != row) {
                                                                moveRow(m_selectedRows.get(0).getIndex(), row.getIndex());
                                                                onRowDraged();
                                                                hoverChanged = true;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                            if (m_hoveredCell != cell) {
                                                if (m_hoveredCell != null) {
                                                    onCellTouchLeave(m_hoveredCell, touchInfo);
                                                }
                                                m_hoveredCell = cell;
                                                onCellTouchEnter(m_hoveredCell, touchInfo);
                                            }
                                            onCellTouchMove(cell, touchInfo);
                                            //检查行的编辑
                                            if (m_editingRow == null) {
                                                if (row.allowEdit()) {
                                                    if (getNative().getPushedView() == this) {
                                                        int selectedRowsSize = m_selectedRows.size();
                                                        if (selectedRowsSize == 1) {
                                                            if (m_selectedRows.get(0) == row) {
                                                                onRowEditBegin(row);
                                                                hoverChanged = true;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                            if (hoverChanged) {
                                                invalidate();
                                            }
                                        }
                                        else {
                                            //触摸按下
                                            if (state == 1) {
                                                onCellTouchDown(cell, touchInfo);
                                                m_touchDownPoint = mp;
                                                if (touchInfo.m_firstTouch || touchInfo.m_secondTouch)
                                                {
                                                    int multiSelectMode = 0;
                                                    //判断是否多选
                                                    if (m_multiSelect) {
                                                        if (host.isKeyPress(0x10)) {
                                                            multiSelectMode = 1;
                                                        }
                                                        else if (host.isKeyPress(0x11)) {
                                                            multiSelectMode = 2;
                                                        }
                                                    }
                                                    //选中单元格
                                                    if (m_selectionMode == FCGridSelectionMode.SelectCell) {
                                                        bool contains = false;
                                                        bool selectedChanged = false;
                                                        int selectedCellSize = m_selectedCells.size();
                                                        if (multiSelectMode == 0 || multiSelectMode == 2) {
                                                            for (int m = 0; m < selectedCellSize; m++) {
                                                                if (m_selectedCells.get(m) == cell) {
                                                                    contains = true;
                                                                    if (multiSelectMode == 2) {
                                                                        m_selectedCells.remove(cell);
                                                                        selectedChanged = true;
                                                                    }
                                                                    break;
                                                                }
                                                            }
                                                        }
                                                        if (multiSelectMode == 0) {
                                                            selectedCellSize = m_selectedCells.size();
                                                            if (!contains || selectedCellSize > 1) {
                                                                m_selectedCells.clear();
                                                                m_selectedCells.add(cell);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        else if (multiSelectMode == 2) {
                                                            if (!contains) {
                                                                m_selectedCells.add(cell);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        if (selectedChanged) {
                                                            onSelectedCellsChanged();
                                                        }
                                                    }
                                                    //选中全列
                                                    else if (m_selectionMode == FCGridSelectionMode.SelectFullColumn) {
                                                        bool contains = false;
                                                        bool selectedChanged = false;
                                                        int selectedColumnsSize = m_selectedColumns.size();
                                                        if (multiSelectMode == 0 || multiSelectMode == 2) {
                                                            for (int m = 0; m < selectedColumnsSize; m++) {
                                                                if (m_selectedColumns.get(m) == column) {
                                                                    contains = true;
                                                                    if (multiSelectMode == 2) {
                                                                        m_selectedColumns.remove(column);
                                                                        selectedChanged = true;
                                                                    }
                                                                    break;
                                                                }
                                                            }
                                                        }
                                                        if (multiSelectMode == 0) {
                                                            if (!contains || selectedColumnsSize > 1) {
                                                                m_selectedColumns.clear();
                                                                m_selectedColumns.add(column);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        else if (multiSelectMode == 2) {
                                                            if (!contains) {
                                                                m_selectedColumns.add(column);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        //单元格必选中
                                                        m_selectedCells.clear();
                                                        m_selectedCells.add(cell);
                                                        if (selectedChanged) {
                                                            onSelectedColumnsChanged();
                                                        }
                                                    }
                                                    //选中全行
                                                    else if (m_selectionMode == FCGridSelectionMode.SelectFullRow) {
                                                        bool contains = false;
                                                        bool selectedChanged = false;
                                                        int selectedRowsSize = m_selectedRows.size();
                                                        if (multiSelectMode == 0 || multiSelectMode == 2) {
                                                            for (int m = 0; m < selectedRowsSize; m++) {
                                                                if (m_selectedRows.get(m) == row) {
                                                                    contains = true;
                                                                    if (multiSelectMode == 2) {
                                                                        m_selectedRows.remove(row);
                                                                        selectedChanged = true;
                                                                    }
                                                                    break;
                                                                }
                                                            }
                                                        }
                                                        if (multiSelectMode == 0) {
                                                            selectedRowsSize = m_selectedRows.size();
                                                            if (!contains || selectedRowsSize > 1) {
                                                                m_selectedRows.clear();
                                                                m_selectedRows.add(row);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        else if (multiSelectMode == 1) {
                                                            selectedRowsSize = m_selectedRows.size();
                                                            if (selectedRowsSize > 0) {
                                                                int firstIndex = m_selectedRows.get(0).getIndex();
                                                                int newIndex = row.getIndex();
                                                                int minIndex = Math.Min(firstIndex, newIndex);
                                                                int maxIndex = Math.Max(firstIndex, newIndex);
                                                                m_selectedRows.clear();
                                                                for (int s = minIndex; s <= maxIndex; s++) {
                                                                    m_selectedRows.add(getRow(s));
                                                                }
                                                            }
                                                            else {
                                                                m_selectedRows.add(row);
                                                            }
                                                        }
                                                        else if (multiSelectMode == 2) {
                                                            if (!contains) {
                                                                m_selectedRows.add(row);
                                                                selectedChanged = true;
                                                            }
                                                        }
                                                        //单元格必选中
                                                        m_selectedCells.clear();
                                                        m_selectedCells.add(cell);
                                                        if (selectedChanged) {
                                                            onSelectedRowsChanged();
                                                        }
                                                    }
                                                }
                                            }
                                            //触摸抬起
                                            else if (state == 2) {
                                                onCellTouchUp(cell, touchInfo);
                                            }
                                            if (state == 2) {
                                                if (m_selectedCells.size() > 0 && m_selectedCells.get(0) == cell) {
                                                    onCellClick(cell, touchInfo);
                                                    if (touchInfo.m_firstTouch && cell.allowEdit()) {
                                                        if ((m_cellEditMode == FCGridCellEditMode.DoubleClick && touchInfo.m_clicks == 2)
                                                            || (m_cellEditMode == FCGridCellEditMode.SingleClick && touchInfo.m_clicks == 1))
                                                        {
                                                            onCellEditBegin(cell);
                                                        }
                                                    }
                                                }
                                            }
                                            invalidate();
                                        }
                                        unFrozenCells.clear();
                                        if (state == 1 && m_editingRow != null) {
                                            //取消行的编辑
                                            onRowEditEnd();
                                        }
                                        return;
                                    }
                                }
                            }
                        }
                        unFrozenCells.clear();
                    }
                }
            }
            if (state == 1 && m_editingRow != null) {
                //取消行的编辑
                onRowEditEnd();
            }
        }

        /// <summary>
        /// 重新布局
        /// </summary>
        public override void update() {
            if (m_native != null && !m_native.m_lockUpdate)
            {
                if (!m_lockUpdate) {
                    base.update();
                    if (isVisible()) {
                        int colSize = m_columns.size();
                        for (int i = 0; i < colSize; i++) {
                            m_columns.get(i).setIndex(i);
                        }
                        int rowSize = m_rows.size();
                        int visibleIndex = 0;
                        int rowTop = m_headerVisible ? m_headerHeight : 0;
                        int allVisibleColumnsWidth = getAllVisibleColumnsWidth();
                        m_hasUnVisibleRow = false;
                        for (int i = 0; i < rowSize; i++) {
                            FCGridRow gridRow = m_rows.get(i);
                            gridRow.setIndex(i);
                            if (gridRow.isVisible()) {
                                gridRow.setVisibleIndex(i);
                                int rowHeight = gridRow.getHeight();
                                FCRect rowRect = new FCRect(0, rowTop, allVisibleColumnsWidth, rowTop + rowHeight);
                                gridRow.setBounds(rowRect);
                                rowTop += rowHeight;
                                visibleIndex++;
                            }
                            else {
                                m_hasUnVisibleRow = true;
                                gridRow.setVisibleIndex(-1);
                                FCRect rowRect = new FCRect(0, rowTop, allVisibleColumnsWidth, rowTop);
                                gridRow.setBounds(rowRect);
                            }
                        }
                        FCHScrollBar hScrollBar = getHScrollBar();
                        FCVScrollBar vScrollBar = getVScrollBar();
                        if (vScrollBar != null && vScrollBar.isVisible()) {
                            int top = m_headerVisible ? m_headerHeight : 0;
                            vScrollBar.setTop(top);
                            int height = getHeight() - top - ((hScrollBar != null && hScrollBar.isVisible()) ? hScrollBar.getHeight() : 0);
                            vScrollBar.setHeight(height);
                            vScrollBar.setPageSize(height);
                            if (rowSize > 0) {
                                //vScrollBar.setLineSize(getAllVisibleRowsHeight() / rowSize);
                            }
                        }
                        m_mustUpdate = false;
                    }
                }
            }
        }

        /// <summary>
        /// 更新列排序
        /// </summary>
        public virtual void updateSortColumn() {
            //重新排序
            int columnSize = m_columns.size();
            for (int i = 0; i < columnSize; i++) {
                if (m_columns.get(i).getSortMode() != FCGridColumnSortMode.None) {
                    sortColumn(this, m_columns.get(i), m_columns.get(i).getSortMode());
                    break;
                }
            }
        }
    }
}
